/******************************************************************************
 * Copyright (C) 2016 Wuhan Water Elephant Co.Ltd All Rights Reserved. 
 * 本软件为武汉水象科技有限公司开发研制。 未经本公司正式书面同意，其他任何个人、
 * 团体不得使用、复制、修改或发布本软件.
 *****************************************************************************/
package com.sxfq.loansupermarket.app.common.controller;

import java.util.Calendar;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.sxfq.loansupermarket.app.constants.AppConstant;
import com.sxfq.loansupermarket.app.dto.AppResponseResult;
import com.sxfq.loansupermarket.business.dto.sms.MessageDto;
import com.sxfq.loansupermarket.common.annotation.LockAndSyncRequest;
import com.sxfq.loansupermarket.common.annotation.LoginIntercept;
import com.sxfq.loansupermarket.common.constants.RedisKeyConstants;
import com.sxfq.loansupermarket.common.utils.ControllerUtil;
import com.sxfq.loansupermarket.common.utils.EncryptionUtil;
import com.sxfq.loansupermarket.common.utils.NumberUtil;
import com.sxfq.loansupermarket.common.utils.RedisUtil;
import com.sxfq.loansupermarket.common.utils.StringUtil;

/**
 * 
 * 
 * Module:
 * 
 * SmsController.java
 * 
 * @author 毛恩奇
 * @since JDK 1.8
 * @version 1.0
 * @description: <描述>
 */
@Controller
@RequestMapping("/sms")
@LoginIntercept(checkLogin = false)
public class SmsController {
	private Logger logger = Logger.getLogger(SmsController.class);
	// 每个手机号每天可发送短信次数
	@Value("${sms.phone.sendDayCount:5}")
	private int sendDayCount;
	// 每个手机发送短信间隔时间
	@Value("${sms.phone.sendIntervalSeconds:60}")
	private int sendIntervalSeconds;
	// 验证码过期时间，单位：分钟
	@Value("${sms.codeExpiredMinutes:10}")
	private int codeExpiredMinutes;

	/**
	 * 
	 * 
	 * @param request
	 * @param response
	 * @param phone
	 * @param smsType
	 *            短信类型：1.登录或注册，2.找回密码
	 * @return
	 */
	public AppResponseResult sendSms(HttpServletRequest request, HttpServletResponse response, String phone,
			Integer smsType) {
		AppResponseResult result = AppResponseResult.build(AppConstant.Code.SUCCESS, AppConstant.Msg.SUCCESS);
		try {
			logger.info("【SmsController.sendSms】phone:" + phone + ",smsType:" + smsType);
			if (smsType == null || (smsType != 1 && smsType != 2)) {
				result.setCode(AppConstant.Code.FAIL);
				result.setMsg("参数错误");
				return result;
			}
			if (StringUtil.isEmpty(phone) || !phone.matches("^1[1-9]\\d{9}$")) {
				result.setCode(AppConstant.Code.FAIL);
				result.setMsg(AppConstant.Msg.FAIL);
				return result;
			}
			// 每个手机号每天发送短信次数
			int smsPhoneCount = NumberUtil.parseInteger(RedisUtil.get(RedisKeyConstants.SMS_PHONE_COUNT_PRE + phone),
					0);
			if (smsPhoneCount >= sendDayCount) {
				result.setCode(AppConstant.Code.FAIL);
				result.setMsg("您的短信次数已达上限，请明天再试");
				return result;
			}
			String smsPhoneDate = RedisUtil.get(RedisKeyConstants.SMS_PHONE_PRE + phone);
			if (StringUtils.isNotEmpty(smsPhoneDate)) {
				result.setCode(AppConstant.Code.FAIL);
				result.setMsg("您发送短信次数过于频繁，请一分钟后重试");
				return result;
			}

			String validateCode = RandomStringUtils.randomNumeric(4);
			// 保存验证码(中间保存的是短信类型，1.登录或注册 2.找回密码)
			RedisUtil.setex(RedisKeyConstants.SMS_CODE_PRE + smsType + ":" + phone, validateCode,
					codeExpiredMinutes * 60);
			MessageDto messageDto = new MessageDto();
			messageDto.setBusinessScenario("1");
			messageDto.setPhone(phone);
			// TODO
			messageDto.setMsg("您的验证码是" + validateCode + "，5分钟内有效，为了您的账户安全，请勿泄露");
			messageDto.setType("1");
			RedisUtil.rpush(RedisKeyConstants.SMS_SEND, JSON.toJSONString(messageDto));
			logger.info("【SmsController.sendSms】phone:" + phone + ",smsType:" + smsType + ",验证码validateCode:"
					+ validateCode);
			Date ceilingDay = DateUtils.ceiling(new Date(), Calendar.DAY_OF_MONTH);
			Date nowDate = new Date();
			// 到今晚凌晨剩余毫秒数
			long milliseconds = ceilingDay.getTime() - nowDate.getTime();
			// 设置手机每天已发短信过期时间，到今晚零点
			RedisUtil.psetex(RedisKeyConstants.SMS_PHONE_COUNT_PRE + phone, (smsPhoneCount + 1) + "", milliseconds);
			// 一分钟只能发一次短信
			RedisUtil.setex(RedisKeyConstants.SMS_PHONE_PRE + phone,
					DateFormatUtils.format(nowDate, "yyyy-MM-dd HH:mm:ss"), sendIntervalSeconds);
		} catch (Exception e) {
			result.setCode(AppConstant.Code.ERROR);
			result.setMsg(AppConstant.Msg.ERROR);
			logger.error("【SmsController.sendSms】发送短信异常,phone:" + phone + ",smsType:" + smsType, e);
		}
		return result;
	}

	/**
	 * APP发送短信，手机号加密
	 * 
	 * @param request
	 * @param response
	 * @param phone
	 * @param smsType
	 * @return
	 */
	@RequestMapping(value = "/sendSmsEncryption")
	@ResponseBody
	@LockAndSyncRequest
	public AppResponseResult sendSmsEncryption(HttpServletRequest request, HttpServletResponse response, String phone,
			Integer smsType) {
		AppResponseResult result = AppResponseResult.build(AppConstant.Code.SUCCESS, AppConstant.Msg.SUCCESS);
		try {
			logger.info(
					"【SmsController.sendSmsEncryption】加密phone:" + phone + ",phone:" + phone + ",smsType:" + smsType);
			logger.info("加密的手机号码：" + phone);
			// 电话号码解密
			phone = EncryptionUtil.getPhone(phone);
			logger.info("解密的手机号码：" + phone);
			if (StringUtils.isEmpty(phone)) {
				result.setCode(AppConstant.Code.FAIL);
				result.setMsg("手机号错误");
				return result;
			}
			logger.info("【SmsController.sendSmsEncryption】phone:" + phone + ",phone:" + phone + ",smsType:" + smsType);
			result = sendSms(request, response, phone, smsType);
		} catch (Exception e) {
			result.setCode(AppConstant.Code.ERROR);
			result.setMsg(AppConstant.Msg.ERROR);
			logger.error("【SmsController.sendSmsEncryption】发送短信异常,phone:" + phone + ",smsType:" + smsType, e);
		}
		return result;
	}

	/**
	 * H5发送短信，加上图片验证码
	 * 
	 * @param request
	 * @param response
	 * @param phone
	 * @param smsType
	 * @return
	 */
	@RequestMapping(value = "/sendSmsByImg")
	@ResponseBody
	@LockAndSyncRequest
	public AppResponseResult sendSmsByImg(HttpServletRequest request, HttpServletResponse response, String phone,
			Integer smsType, String imgCode) {
		AppResponseResult result = AppResponseResult.build(AppConstant.Code.SUCCESS, AppConstant.Msg.SUCCESS);
		try {
			logger.info("【SmsController.sendSmsByImg】phone:" + phone + ",phone:" + phone + ",smsType:" + smsType);
			String businessToken = ControllerUtil.getOrCreateBusinessToken(request, response);
			String imgRedisKey = RedisKeyConstants.IMG_VERIFY_CODE_PRE + businessToken.hashCode();
			String redisImgCode = RedisUtil.get(imgRedisKey);
			if (StringUtils.isEmpty(imgCode) || !imgCode.equalsIgnoreCase(redisImgCode)) {
				result.setCode(AppConstant.Code.FAIL);
				result.setMsg("图片验证码不匹配");
				return result;
			}
			result = sendSms(request, response, phone, smsType);
			if (AppConstant.Code.SUCCESS.equals(result.getCode())) {
				RedisUtil.del(imgRedisKey);
			}
		} catch (Exception e) {
			result.setCode(AppConstant.Code.ERROR);
			result.setMsg(AppConstant.Msg.ERROR);
			logger.error("【SmsController.sendSmsByImg】发送短信异常,phone:" + phone + ",smsType:" + smsType, e);
		}
		return result;
	}
}